/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package helloscala.practise.chapter9

import scala.actors.Actor
import scala.actors.Actor._
import scala.collection.mutable.ArrayBuffer
import scala.util.Random

case class Haircut(shop: Shop)
case class Paid(customer: Customer)

class Customer(val id: Int) extends Actor {
  var shorn = false
  def act = {
    loop {
      react {
        case hairCut: Haircut => {
          shorn = true
          println("[c] Customer " + id + " got a haircut")}
          hairCut.shop ! new Paid(this)
          exit //once complete cut, no more waiting
      }
    }
  }
}

class Barber(shop: Shop) extends Actor {
  val random = new Random()
  var free = true

  def act = {
    loop {
      react {
        case customer: Customer if free => free = false; helpCustomer(customer)
        case paid: Paid => free = true
      }
    }
  }

  def helpCustomer(customer: Customer) = {
    if (this.mailboxSize >= 3) {
      println("[b] Not enough seats, turn customer " + customer.id + " away")
      free = true
    } else {
      println("[b] cutting hair of cutomer " + customer.id)
      Thread.sleep(100 + random.nextInt(400))
      customer ! new Haircut(shop)
    }
  }
}

class Shop extends Actor {
  val barber = new Barber(this)
  barber.start

  def act = {
    println("Barber Shop opened!")
    loop {
      react {
        case customer: Customer => barber ! customer
        case paid: Paid => {
          println("[!] Customer " + paid.customer.id + " paid")
          barber ! paid
        }
      }
    }
  }
}

object BarberShopSimulator {
  private val random = new Random
  private val shop = new Shop
  private val customers = new ArrayBuffer[Customer]

  def generateCustomers(seed: Int) = {
    for (i <- seed to seed + 19) {
      val customer = new Customer(i)
      customer.start //wait to be cut before go in shop
      //customers append(customer)
      customers += customer
    }
  }

  def trickleCustomers = {
    for (customer <- customers) {
      shop ! customer
      Thread.sleep(random.nextInt(450))
    }
  }

  def tallyCustomers = {
    val shornList = customers.filter(c => c.shorn)
    val unShornList = customers.filterNot(c => c.shorn)
    val shornCount = shornList.size

    println("[!] " + shornCount + " customers got shorn today")
    println("The unshorn guys are: ")
    for (customer <- unShornList) {
      println("Customer: " + customer.id)
    }
  }

  def startSimulate = {
    println("[!] Starting Barbershop simulation")
    shop.start

    generateCustomers(1)
    trickleCustomers
    
    Thread.sleep(5000) //give some time for complete customer queue
    tallyCustomers

    System.exit(0)
  }
}